<template>
  <div ref="mapRef" class="map">
    <HourTimeQueryTool ref="timeQueryToolRef" @time-query="queryHeatmapData" class="time_query"/>
  </div>
</template>
<script setup>
import {
  defineProps,
  defineExpose,
  onMounted,
  ref,
  watch,
  defineEmits
} from 'vue';
// 组件属性
import { useRouter } from 'vue-router';
import CarManager from '@/utils/CarManager.js';
import HourTimeQueryTool from './HourTimeQueryTool.vue';
import { getHeatmapData } from '@/api/overview';
import CoordinateUtil from '@/utils/CoordinateUtil';
const router = useRouter();
const mapRef = ref(null);
const timeQueryToolRef = ref(null);
const HEIGHT_LEVEL_4 = 6045600;
const HEIGHT_LEVEL_14 = 6700;

let map;

const areaList = [
  {
    id: 3,
    name: '亦庄',
    value: [116.503793, 39.791357],
    pixelOffset: [-15, 0]
  },
  {
    id: 5,
    name: '太和桥',
    value: [116.544495, 39.745386],
    pixelOffset: [15, 15]
  },
  {
    id: 1,
    name: '苏州',
    value: [120.565129, 31.301071],
    pixelOffset: [-10, 0]
  },
  {
    id: 4,
    name: '南京',
    value: [118.721258, 32.062963],
    pixelOffset: [-5, 0]
  },
  {
    id: 2,
    name: '上海',
    value: [121.443624, 31.193505],
    pixelOffset: [10, 10]
  }
];

// 加载底图
const loadMap = () => {
  map = new Cesium.Viewer(mapRef.value, {
    useDefaultRenderLoop: true, // 是否自动渲染
    geocoder: false, // 地理位置查询定位控件
    homeButton: false, // 默认相机位置控件
    timeline: false, // 时间滚动条控件
    navigationHelpButton: false, // 默认的相机控制提示控件
    fullscreenButton: false, // 全屏控件
    baseLayerPicker: false, // 底图切换控件
    animation: false, // 控制场景动画的播放速度控件
    selectionIndicator: false, // 取消双击追踪实体行为
    requestRenderMode: false, // 如果为 true，则仅在场景中的变化所确定的需要时才会渲染帧。
    maximumRenderTimeChange: Infinity, // 如果requestRenderMode为true，这个值定义了在请求渲染之前允许的模拟时间的最大变化。
    sceneModePicker: false, // 不创建SceneModePicker小部件。
    infoBox: false, // 不创建 InfoBox 小部件。
    navigationInstructionsInitiallyVisible: false, // 如果导航说明最初应该是可见的，则为真，如果在用户明确单击按钮之前不应显示，则为假。
    imageryProvider: new Cesium.UrlTemplateImageryProvider({
      url: 'https://map.geoq.cn/arcgis/rest/services/ChinaOnlineStreetPurplishBlue/MapServer/tile/{z}/{y}/{x}'
    }), // 初始化默认球皮
    shouldAnimate: false, // 用于开启时钟视图模型
    sceneMode: Cesium.SceneMode.COLUMBUS_VIEW,
    showRenderLoopErrors: false, // 是否显示错误弹框
    orderIndependentTranslucency: true // 如果为 true 且配置支持，则使用与顺序无关的半透明。
  });
  // 开启抗锯齿
  map.scene.postProcessStages.fxaa.enabled = true;
  // js版本存在判断是否支持图像渲染像素化处理，目前不存在。后续可让用于自定义传入
  if (Cesium.defined(window.devicePixelRatio)) {
    // 设置屏幕分辨率尺度，解决渲染锯齿严重问题
    map.resolutionScale = window.devicePixelRatio;
  }
  // 移除双击追踪事件
  map.cesiumWidget.screenSpaceEventHandler.removeInputAction(
    Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK
  );
  /**
   *  在测试是否与地形发生碰撞之前，摄像机必须达到的最小高度。 此参数在旋转角度时，
   *  若当前高度大于此高度会根据数据移动点y轴计算渲染
   */
  map.scene.screenSpaceCameraController.minimumCollisionTerrainHeight = 1;
  // 修改操作模式左键平移、中键缩放、右键旋转
  map.scene.screenSpaceCameraController.zoomEventTypes = [
    Cesium.CameraEventType.WHEEL,
    Cesium.CameraEventType.PINCH
  ];
  map.scene.screenSpaceCameraController.tiltEventTypes = [
    Cesium.CameraEventType.PINCH,
    Cesium.CameraEventType.RIGHT_DRAG
  ];
  // 隐藏Cesium icon显示
  map.cesiumWidget.creditContainer.setAttribute('style', 'display:none');
  // 无论是否开启动画,隐藏Cesium动画控件
  const animationElements = document.getElementsByClassName(
    'cesium-viewer-animationContainer'
  );
  if (Cesium.defined(animationElements) && animationElements.length > 0) {
    animationElements[0].setAttribute('style', 'display:none');
  }
  // 无论是否开启时间轴,隐藏Cesium时间轴控件
  const timelineElements = document.getElementsByClassName(
    'cesium-viewer-timelineContainer'
  );
  if (Cesium.defined(timelineElements) && timelineElements.length > 0) {
    timelineElements[0].setAttribute('style', 'display:none');
  }
  map.scene.screenSpaceCameraController.maximumZoomDistance = 6045564;
  map.camera.setView({
    destination: Cesium.Cartesian3.fromDegrees(
      104.891698927843058,
      35.129290803042717,
      6045564.31073331
    )
  });
  addLabel();
  // 用于适应高度改变之后标签位置移动
  map.scene.postRender.addEventListener(() => {
    const height = window.map.camera.positionCartographic.height;
    const entities = map.entities.values;
    if (height < 30000) {
      entities.forEach(item => {
        item.label.pixelOffset = new Cesium.Cartesian2(0, 0);
      });
    } else {
      entities.forEach(item => {
        const index = areaList.findIndex(ele => ele.id === item.id);
        if (index !== -1) {
          const pixelOffset = areaList[index].pixelOffset;
          item.label.pixelOffset = new Cesium.Cartesian2(pixelOffset[0], pixelOffset[1]);
        }
      });
    }
  });
  // 函数防抖
  function debounce (func, wait) {
    let timer;
    return function () {
      const context = this; // 注意 this 指向
      const args = arguments; // arguments中存着e
      if (timer) clearTimeout(timer);
      timer = setTimeout(() => {
        func.apply(context, args);
      }, wait);
    };
  }
  //
  map.camera.moveEnd.addEventListener(() =>{
    const height = map.camera.positionCartographic.height;
    if(height > HEIGHT_LEVEL_4 || height < HEIGHT_LEVEL_14) {
      if(heatmap) heatmap.removeLayer();
      return;
    };
    debounce(() => {
      if(heatmap) heatmap.removeLayer();
      queryHeatmapData();
    }, 200)();
  });
  window.map = map;
};

function addLabel () {
  for (let i = 0; i < areaList.length; i++) {
    const info = areaList[i];
    map.entities.add({
      id: info.id,
      position: Cesium.Cartesian3.fromDegrees(info.value[0], info.value[1], 0),
      label: {
        text: info.name,
        font: 'normal 1rem PingFang SC-Regular, PingFang SC', // 字体样式
        fillColor: Cesium.Color.fromCssColorString('#9BD5FF'), // 字体颜色
        backgroundColor:
          Cesium.Color.fromCssColorString('rgba(0, 0, 0, 0.7)').withAlpha(0.8), // 背景颜色
        showBackground: true, // 是否显示背景颜色
        outlineWidth: 2,
        verticalOrigin: Cesium.VerticalOrigin.CENTER, // 垂直位置
        horizontalOrigin: Cesium.HorizontalOrigin.LEFT, // 水平位置
        pixelOffset: new Cesium.Cartesian2(info.pixelOffset[0], info.pixelOffset[1])
      }
    });
  }
  window.map = map;
  const handler = new Cesium.ScreenSpaceEventHandler(map.scene.canvas);
  handler.setInputAction((evt) => {
    const pick = map.scene.pick(evt.position);
    if (Cesium.defined(pick) && pick.id) {
      const entity = pick.id;
      router.push({
        path: '/Area',
        query: {
          id: entity.id
        }
      });
    }
  }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
}
let heatmap;
let lastQueryBbox;
const queryHeatmapData = (timeRange) => {
  let bbox = getBBox();
  if(bbox){
    const {startTime, endTime } = timeRange || timeQueryToolRef.value.getTimeRange();
    const data = {
      divisionNumber: 9,
      endTime:1663042221610,
      startTime:1663038621610,
      bbox
    }
    const bounds = {
      west: bbox[0],
      south: bbox[1],
      east: bbox[2],
      north: bbox[3]
    }
    getHeatmapData(data).then(({resCode, data})=>{
      if(resCode !== '00000') return;
      if(lastQueryBbox && lastQueryBbox !== bbox ) return;
      let max = 0;
      const sourceData = []
      console.log(Date.now())
      data.forEach(({latLngs, number}) => {
        if(number > 0){
          let lon = 0;
          let lat = 0;
          latLngs.forEach(({longitude, latitude})=>{
            lon += longitude;
            lat += latitude;
          })
          const [x, y] = CoordinateUtil.wgs84togcj02(lon/4, lat/4);
          sourceData.push({
            x,y,
            value: number
          })
          max = Math.max(max, number);
        } 
      })
      if(heatmap){
        heatmap.changeBounds(bounds)
      }else{
        heatmap =  CesiumHeatmap.create(
          map, // 视图层
          bounds, // 矩形坐标
          { // heatmap相应参数
            maxOpacity: 1,
            minOpacity: 0,
            radius: 140,
            backgroundColor: 'rgba(255, 0, 0, 0)',
            blur: .95
          }
        )
      }
      heatmap.setWGS84Data(10, max, sourceData);
      map.scene.requestRender();
    })
    lastQueryBbox = bbox;
  }
}

const getBBox = () =>{
  const [xMin, yMin, xMax, yMax] = CarManager.getRange(map);
  if(xMin&&yMin&&xMax&&yMax&&xMin!= -180){
    const [_xmin, _ymax] = CoordinateUtil.gcj02towgs84(xMin, yMax);
    const [_xmax, _ymin] = CoordinateUtil.gcj02towgs84(xMax, yMin);
    return [_xmin, _ymin, _xmax, _ymax];
  }else{
    return undefined
  }
}
/** 组件挂载后事件回调 */
onMounted(() => {
  loadMap();
});

defineExpose({});
</script>
<style scoped>
.map {
  width: 100%;
  height: 100%;
  position: absolute;
  left: 0;
}

.time_query {
  position: absolute;
  left: 1rem;
  top: 1rem;
  z-index: 100;
}
</style>
